#!/usr/bin/python2
# -*- coding: utf-8 -*-

"""
Copyright (c) 2010, Philip Busch <philip@0xe3.com>
See License.txt for details.
"""

import sys
import pygtk
pygtk.require('2.0')
import gtk
import pango


__appname__ = 'pyme'
__author__ = ['Philip Busch <vzxwco@gmail.com>']
__version__ = '0.2'
__license__ = 'BSD'
__website__ = 'http://code.google.com/p/pyme/'


class Pyme:
	ui = '''
<ui>
  <menubar name="Menubar">
    <menu action="File">
      <menuitem action="New"/>
      <menuitem action="Open"/>
      <menuitem action="Save"/>
      <menuitem action="Save As"/>
      <separator />
      <menuitem action="Quit"/>
    </menu>
    <menu action="Help">
      <menuitem action="About"/>
    </menu>
  </menubar>
</ui>
'''

	def delete_event(self, widget, event, data=None):
		'''Event handler for the delete event.'''
		if self.get_modified():
			if self.save_changes() == False:
				return True

		return False

	def destroy(self, widget, data=None):
		'''Quit GTK.'''
		gtk.main_quit()

	def new(self, w):
		'''Opens a new file.'''
		if self.get_modified():
			if self.save_changes() == False:
				return

		textbuffer = gtk.TextBuffer()
		textbuffer.set_modified(False)
		self.textview.set_buffer(textbuffer)
		self.filename = None
		self.update_titlebar()

	def open(self, w):
		'''Opens an existing file.'''
		if self.get_modified():
			if self.save_changes() == False:
				return

		chooser = gtk.FileChooserDialog(title='Open File...',
			action=gtk.FILE_CHOOSER_ACTION_OPEN,
			buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
				 gtk.STOCK_OPEN, gtk.RESPONSE_OK))

		response = chooser.run()
		filename = chooser.get_filename()
		chooser.destroy()

		if response != gtk.RESPONSE_OK:
			return

		self.open_file(filename)

	def open_file(self, filename):
		try:
			fd = open(filename, 'r')
		except IOError:
			text = u""
		else:
			file = fd.read()
			fd.close()

			try:
				text = unicode(file)
			except UnicodeDecodeError:
				self.dialog_error("File is not encoded as UTF-8, forcing UTF-8.")
				text = unicode(file, errors='replace')

		self.filename = filename
		self.update_titlebar()

		textbuffer = gtk.TextBuffer()
		textbuffer.set_text(text)
		textbuffer.set_modified(False)
		self.textview.set_buffer(textbuffer)

	def save(self, w):
		'''Saves the current file.'''
		if self.filename == None:
			self.saveas(None)
		else:
			try:
				fd = open(self.filename, 'w')
			except IOError:
				self.dialog_error("Can't write to file " +
					self.filename)
			else:
				textbuffer = self.textview.get_buffer()
				(start, end) = textbuffer.get_bounds()
				text = textbuffer.get_text(start, end)
				fd.write(text)
				fd.close()
				textbuffer.set_modified(False)

	def saveas(self, w):
		'''Saves the current file, too.'''
		chooser = gtk.FileChooserDialog(title='Save As...',
			action=gtk.FILE_CHOOSER_ACTION_SAVE,
			buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
				 gtk.STOCK_OPEN, gtk.RESPONSE_OK))
		response = chooser.run()
		filename = chooser.get_filename()
		chooser.destroy()

		if response != gtk.RESPONSE_OK:
			return

		self.filename = filename
		self.update_titlebar()
		self.save(None)

	def quit(self, w):
		'''Quits the application.'''
		if self.get_modified():
			if self.save_changes() == False:
				return

		gtk.main_quit()

	def about(self, w):
		'''Shows an about dialog.'''
		about = gtk.AboutDialog()

		about.set_name(__appname__)
		about.set_authors(__author__)
		about.set_version(__version__)
		about.set_comments('Minimalist Editor')
		about.set_copyright('Copyright (c) 2011 Philip Busch')
		about.set_website(__website__)
		about.set_program_name(__appname__)
		about.run()
		about.hide()

	def update_titlebar(self):
		'''Updates the titlebar.'''
		if self.filename == None:
			text = __appname__
		else:
			text = self.filename + " - " + __appname__

		self.window.set_title(text)

	def get_modified(self):
		'''Checks whether the textbuffer has been modified.'''
		textbuffer = self.textview.get_buffer()
		return textbuffer.get_modified()

	def dialog_error(self, message):
		'''A generic error message dialog.'''
		dialog = gtk.Dialog(title='Error', parent=self.window,
			flags=gtk.DIALOG_MODAL,
			buttons=(gtk.STOCK_OK, gtk.RESPONSE_OK))
		label = gtk.Label("\n" + message + "\n")
		dialog.vbox.pack_start(label, True, True, 0)
		label.show()
		dialog.run()
		dialog.destroy()

	def dialog_modified(self):
		'''Shows the "Save changes" dialog.'''
		dialog = gtk.Dialog(title='Warning', parent=self.window,
				flags=gtk.DIALOG_MODAL,
				buttons=(gtk.STOCK_YES, gtk.RESPONSE_YES,
				gtk.STOCK_NO, gtk.RESPONSE_NO,
				gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL))
		label = gtk.Label("\nDo you want to save your changes?\n")
		dialog.vbox.pack_start(label, True, True, 0)
		label.show()
		response = dialog.run()
		dialog.destroy()

		if response == gtk.RESPONSE_YES:
			return True
		elif response == gtk.RESPONSE_NO:
			return False
		elif response == gtk.RESPONSE_CANCEL or response == gtk.RESPONSE_NONE:
			return None

	def save_changes(self):
		'''Saves changes if user wants to.'''
		response = self.dialog_modified()

		if response == True:
			self.save(None)
			return True
		elif response == False:
			return True
		elif response == None:
			return False

	def __init__(self):
		'''Creates main window and sets all variables to their defailts.'''
		self.filename = None

		self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
		self.window.connect("delete_event", self.delete_event)
		self.window.connect("destroy", self.destroy)
		self.window.set_default_size(700, 400)

		uimanager = gtk.UIManager()
		uimanager.add_ui_from_string(self.ui)
		accelgroup = uimanager.get_accel_group()
		self.window.add_accel_group(accelgroup)

		actiongroup = gtk.ActionGroup('Pyme')
		actiongroup.add_actions([
			('File', None, '_File'),
			('New', None, '_New', None, 'Quit the program', self.new),
			('Open', None, '_Open...', None, 'Quit the program', self.open),
			('Save', None, '_Save', None, 'Quit the program', self.save),
			('Save As', None, 'S_ave As...', None, 'Quit the program', self.saveas),
			('Quit', None, '_Quit', None, 'Quit the program', self.quit),
			('Help', None, '_Help'),
			('About', gtk.STOCK_ABOUT, '_About', None, 'Program Info', self.about)
		])

		uimanager.insert_action_group(actiongroup, 0)

		menubar = uimanager.get_widget('/Menubar')

		textbuffer = gtk.TextBuffer(None)
		textbuffer.set_modified(False)
		self.textview = gtk.TextView(textbuffer)

		fontdesc = pango.FontDescription("monospace")
		self.textview.modify_font(fontdesc)

		scrolled_window = gtk.ScrolledWindow(None, None)
		scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
		#scrolled_window.add_with_viewport(textview)
		scrolled_window.add(self.textview)

		self.statusbar = gtk.Statusbar()

		vbox = gtk.VBox()
		vbox.pack_start(menubar, False)
		vbox.pack_start(scrolled_window, True, True, 0)
		vbox.pack_start(self.statusbar, False)
		self.window.add(vbox)

		self.window.show_all()

	def main(self):
		'''Runs the main GTK loop.'''
		gtk.main()

if __name__ == "__main__":
	argc = len(sys.argv)

	if argc == 1:
		pyme = Pyme()
		pyme.main()
	elif argc == 2:
		pyme = Pyme()
		pyme.open_file(sys.argv[1])
		pyme.main()
	else:
		print "USAGE: " + __appname__ + " [file]"


